package com.xinyuan.service;

import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;
import org.apache.poi.ss.usermodel.*;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Classname AccessWork
 * @Description TODO
 * @Date 2020/6/3 9:21
 * @Created by zfl
 */
public class AccessWork {
    //接近工时表：接近和接近工时
    public Map<String, Double> singleAccessTimeMap = new HashMap<String, Double>();
    //每个包对应的接近字段
    public Map<Integer, Set<String>> accessSetMapA = new HashMap<Integer, Set<String>>();
    //A包接近工时
    public Map<Integer, Double> accessTimeMapA = new HashMap<Integer, Double>();
    //C包的接近字段
    public Map<Integer, Set<String>> accessSetMapC = new HashMap<Integer, Set<String>>();
    //C包接近工时
    public Map<Integer, Double> accessTimeMapC = new HashMap<Integer, Double>();
    //
    public Set<String> accessSetA = new HashSet<String>();
    public Set<String> accessSetC = new HashSet<String>();
    //A包总接近工时
    public Double accessTimeATotal = 0.0;
    //C包总接近工时
    public Double accessTimeCTotal = 0.0;


    private void initAccess(int maxA, int intervA, int maxC, int intervC){
        int sizeA = maxA * 12 / intervA;
        for(int i = 1; i <= sizeA; i++){
            accessSetMapA.put(i, new HashSet<String>());
        }
        for(int i = 1; i <= sizeA; i++){
            accessTimeMapA.put(i, 0.0);
        }
        int sizeC = maxC * 12 / intervC;
        for(int i = 1; i <= sizeC; i++){
            accessSetMapC.put(i, new HashSet<String>());
        }
        for(int i = 1; i <= sizeC; i++){
            accessTimeMapC.put(i, 0.0);
        }
    }

    // 根据首检和重检填入包接近
    private void setAccessByCheck(Set<String> access, int topCheck, int reCheck, Map<Integer, Set<String>> accessSetMap){
        if(topCheck == 0 && reCheck == 0){ }
        else if(topCheck == 0){//首检<重检
            for(int i = reCheck; i <= accessSetMap.size(); i += reCheck){
                accessSetMap.get(i).addAll(access);
            }
        }
        else if(reCheck == 0){//首检>重检
            for(int i = topCheck; i <= accessSetMap.size(); i += topCheck){
                accessSetMap.get(i).addAll(access);
            }
        }
        else if(topCheck == reCheck){//首检和重检相等
            for(int i = topCheck; i <= accessSetMap.size(); i += topCheck){
                accessSetMap.get(i).addAll(access);
            }
        }
        else if(topCheck < reCheck){//首检<重检，两个倍数都计算
            for(int i = topCheck; i <= accessSetMap.size(); i += topCheck){
                accessSetMap.get(i).addAll(access);
            }
            for(int i = reCheck; i <= accessSetMap.size(); i += reCheck){
                if((i % topCheck) != 0) {
                    accessSetMap.get(i).addAll(access);
                }
            }
        }
        else{//首检>重检,假设首检4A，重检1A
            for(int i = topCheck; i <= accessSetMap.size(); i += topCheck){//计算4A的倍数4、8、12
                //System.out.println("topCheck = " + topCheck + " i = " + i);
                accessSetMap.get(i).addAll(access);
            }
            for(int i = reCheck * 2; i <= accessSetMap.size(); i += reCheck){//计算1A的倍数，2、3、4、5、6
                //System.out.println("reCheck = " + reCheck + " i = " + i);
                if((i / topCheck) >= 1 && (i % topCheck) != 0) {
                    accessSetMap.get(i).addAll(access);
                }
            }
        }
    }

    // 解析接近
    private Set<String> parseAccess(String check) {
        Set<String> newString = new HashSet<String>();
        Pattern r = Pattern.compile("([0-9]+[A-Z]+)[\\s\\S]?");
        Matcher m = r.matcher(check);
        while(m.find()){
            if(m.groupCount() >= 1){
                newString.add(m.group(1));
            }
        }
        return newString;
    }

    // 解析重检首检字段
    private int parseCheck(String check) {
        Pattern r = Pattern.compile("([0-9]+)[^0-9]?([AC])");
        Matcher m = r.matcher(check);
        if(m.find()){
            if(m.groupCount() >= 1){
                return Integer.parseInt(m.group(1));
            }
        }
        return -1;
    }

    // 解析类型
    private int parseMethod(String check) {
        Pattern r = Pattern.compile("([0-9]+)[^0-9]?([AC])");
        Matcher m = r.matcher(check);
        if(m.find()){
            if(m.groupCount() >= 1){
                if(m.group(2).charAt(0) == 'A') return 0;
                if(m.group(2).charAt(0) == 'C') return 1;
            }
        }
        return -1;
    }

    // 读取每一行，填写接近
    private void readAccessInExcel(String filePath) throws IOException {

        File file = new File(filePath);
        //Cell cell = null;
        //MTOP_ACCESS,MTOP_THRESHOL,MTOP_INTERV
        int accessNum = 0,thresholNum = 0,intervNum = 0;
        FileInputStream stream = new FileInputStream(file);

        Workbook workbook = WorkbookFactory.create(stream);
        Sheet sheet = (Sheet) workbook.getSheetAt(0);

        Row row0 = sheet.getRow(2);
        //获取第一行的最后一个单元格的数值
        int lastCellNum=row0.getLastCellNum();
        //System.out.println(lastCellNum);
        for (int i = 0; i < lastCellNum; i++) {
            Cell cell = row0.getCell(i);
            if(cell.getStringCellValue().equalsIgnoreCase("MTOP_ACCESS")) {
                accessNum = i;
                //System.out.println("access: " + accessNum);
            }else if(cell.getStringCellValue().equalsIgnoreCase("MTOP_THRESHOL")) {
                thresholNum = i;
                //System.out.println("threshol: " + thresholNum);
            }else if(cell.getStringCellValue().equalsIgnoreCase("MTOP_INTERV")){
                intervNum = i;
                //System.out.println("intervNum: " + intervNum);
            }
        }

        for(int i = 3; i <= sheet.getLastRowNum(); i++){
            //i行的接近、首检、重检
            Row row1 = sheet.getRow(i);
            Set<String> access = new HashSet<String>();
            if(row1.getCell(accessNum) != null){
                access = parseAccess(row1.getCell(accessNum).getStringCellValue());
            }

            int topCheck = parseCheck(row1.getCell(thresholNum).getStringCellValue());
            //System.out.println("topCheck = " + topCheck);
            int reCheck = parseCheck(row1.getCell(intervNum).getStringCellValue());
            //ystem.out.println("reCheck = " + reCheck);
            int method = parseMethod(row1.getCell(thresholNum).getStringCellValue());
            if(method == 0){//A检
                setAccessByCheck(access, topCheck, reCheck, accessSetMapA);
            }
            else{//C检
                setAccessByCheck(access, topCheck, reCheck, accessSetMapC);
            }
        }
        workbook.close();
        stream.close();
    }

    //缓存接近工时表
    private void initSingleTimeInExcel(String filePath) throws IOException{
        File file = new File(filePath);
        FileInputStream stream = new FileInputStream(file);

        Workbook workbook = WorkbookFactory.create(stream);
        Sheet sheet = (Sheet) workbook.getSheetAt(0);
        for(int i = 1; i < sheet.getLastRowNum(); i++){
            Row row = sheet.getRow(i);
            String accessName = row.getCell(0).getStringCellValue();
            Double time = row.getCell(2).getNumericCellValue() * row.getCell(3).getNumericCellValue();
            singleAccessTimeMap.put(accessName, time);
        }
        workbook.close();
        stream.close();
    }

    //填写接近
    private void fillAccessTimeMap(){
        for(int i = 1; i <= accessSetMapA.size(); i++){
            for(String a : accessSetMapA.get(i)){
                if(singleAccessTimeMap.get(a) != null){
                    accessTimeMapA.put(i, accessTimeMapA.get(i) + singleAccessTimeMap.get(a));
                }
            }
        }

        for(int i = 1; i <= accessSetMapC.size(); i++){
            for(String a : accessSetMapC.get(i)){
                //判断access字段是否存在
                if(singleAccessTimeMap.get(a) != null){
                    accessTimeMapC.put(i, accessTimeMapC.get(i) + singleAccessTimeMap.get(a));
                }
            }
        }
    }

    //计算总接近
    private void addAllAccess() {
        for (int i = 1; i <= accessSetMapA.size(); i++) {
            accessSetA.addAll(accessSetMapA.get(i));
        }
        for (int i = 1; i <= accessSetMapC.size(); i++) {
            accessSetC.addAll(accessSetMapC.get(i));
        }
        for (String a : accessSetA) {
            if (singleAccessTimeMap.get(a) != null) {
                accessTimeATotal += singleAccessTimeMap.get(a);
            }
        }
        for (String a : accessSetC) {
            if (singleAccessTimeMap.get(a) != null) {
                accessTimeCTotal += singleAccessTimeMap.get(a);
            }
        }
    }
    //封装好的计算
    public void calculateAll(String MTOP, String Access, int maxA, int intervA, int maxC, int intervC) throws IOException{
        initAccess(maxA, intervA, maxC, intervC);
        readAccessInExcel(MTOP);
        initSingleTimeInExcel(Access);
        fillAccessTimeMap();
        addAllAccess();
    }
}